#!/usr/bin/env node

/**
 * Metrics Display Script
 *
 * Command-line tool to display current metrics and statistics
 */

const SimpleMetricsCollector = require('../lib/monitoring/simple-metrics-collector');
const ConfigManager = require('../config-manager');

class MetricsCLI {
    constructor() {
        this.configManager = new ConfigManager();
        this.metricsCollector = new SimpleMetricsCollector(this.configManager);
    }

    /**
     * Display current metrics
     */
    async displayCurrentMetrics() {
        console.log('📊 Vision Analyzer Metrics');
        console.log('=======================\n');

        try {
            // Initialize metrics collector
            this.metricsCollector.initialize();

            // Get current metrics
            const metrics = this.metricsCollector.getCurrentMetrics();
            const summary = this.metricsCollector.getMetricsSummary();

            // Display summary
            console.log('📈 Summary:');
            console.log(`   Uptime: ${this.formatUptime(summary.summary.uptime)}`);
            console.log(`   Total Requests: ${summary.summary.totalRequests}`);
            console.log(`   Error Rate: ${summary.summary.errorRate}%`);
            console.log(`   Avg Response Time: ${summary.summary.avgResponseTime}ms\n`);

            // Display counters
            console.log('🔢 Counters:');
            for (const [name, value] of Object.entries(metrics.counters)) {
                console.log(`   ${name}: ${value}`);
            }
            console.log('');

            // Display gauges
            console.log('📊 Gauges:');
            for (const [name, value] of Object.entries(metrics.gauges)) {
                if (name.includes('bytes')) {
                    console.log(`   ${name}: ${this.formatBytes(value)}`);
                } else if (name.includes('percent')) {
                    console.log(`   ${name}: ${value.toFixed(1)}%`);
                } else {
                    console.log(`   ${name}: ${value}`);
                }
            }
            console.log('');

            // Display histograms
            console.log('📊 Histograms:');
            for (const [name, histogram] of Object.entries(metrics.histograms)) {
                console.log(`   ${name}:`);
                console.log(`     Count: ${histogram.count}`);
                console.log(`     Sum: ${histogram.sum}`);
                console.log(`     Mean: ${histogram.mean}`);
                console.log(`     Median: ${histogram.median}`);
                console.log(`     P95: ${histogram.p95}`);
                console.log(`     P99: ${histogram.p99}`);
            }
            console.log('');

        } catch (error) {
            console.error('❌ Failed to retrieve metrics:', error.message);
            process.exit(1);
        }
    }

    /**
     * Display metrics history
     */
    async displayMetricsHistory(duration = 3600000) {
        console.log('📈 Metrics History');
        console.log('==================\n');

        try {
            this.metricsCollector.initialize();
            const history = this.metricsCollector.getMetricsHistory(duration);

            if (history.length === 0) {
                console.log('No metrics history available');
                return;
            }

            console.log(`Showing ${history.length} samples from the last ${this.formatDuration(duration)}:\n`);

            // Display table header
            console.log('Timestamp                    | Requests | Errors |  Memory | CPU');
            console.log('-----------------------------|----------|--------|--------|------');

            // Display data
            history.slice(-20).forEach(snapshot => {
                const timestamp = new Date(snapshot.timestamp).toLocaleString();
                const requests = snapshot.counters.requests_total || 0;
                const errors = snapshot.counters.requests_failed || 0;
                const memory = this.formatBytes(snapshot.gauges.memory_usage_bytes || 0);
                const cpu = `${snapshot.gauges.cpu_usage_percent || 0}%`;

                console.log(`${timestamp} | ${requests.toString().padStart(8)} | ${errors.toString().padStart(6)} | ${memory.padStart(7)} | ${cpu}`);
            });

            console.log('');

        } catch (error) {
            console.error('❌ Failed to retrieve metrics history:', error.message);
            process.exit(1);
        }
    }

    /**
     * Display health status
     */
    async displayHealthStatus() {
        console.log('🏥 Health Status');
        console.log('===============\n');

        try {
            this.metricsCollector.initialize();
            const health = this.metricsCollector.getHealthStatus();

            // Display status with emoji
            const statusEmoji = health.status === 'healthy' ? '✅' :
                              health.status === 'degraded' ? '⚠️' : '❌';

            console.log(`${statusEmoji} Status: ${health.status.toUpperCase()}`);

            // Display metrics
            console.log(`📊 Error Rate: ${health.metrics.errorRate}%`);
            console.log(`⚡ Response Time: ${health.metrics.avgResponseTime}ms`);
            console.log(`💾 Memory Usage: ${health.metrics.memoryUsagePercent.toFixed(1)}%`);
            console.log(`⏱️  Uptime: ${this.formatUptime(health.metrics.uptime)}\n`);

            // Display issues if any
            if (health.issues.length > 0) {
                console.log('⚠️  Issues:');
                health.issues.forEach(issue => {
                    console.log(`   • ${issue}`);
                });
                console.log('');
            }

        } catch (error) {
            console.error('❌ Failed to get health status:', error.message);
            process.exit(1);
        }
    }

    /**
     * Export metrics in Prometheus format
     */
    async exportPrometheusMetrics() {
        try {
            this.metricsCollector.initialize();
            const metrics = this.metricsCollector.getPrometheusMetrics();
            console.log(metrics);
        } catch (error) {
            console.error('❌ Failed to export metrics:', error.message);
            process.exit(1);
        }
    }

    /**
     * Generate metrics report
     */
    async generateReport() {
        console.log('📋 Metrics Report');
        console.log('================\n');

        try {
            this.metricsCollector.initialize();
            const summary = this.metricsCollector.getMetricsSummary();
            const history = this.metricsCollector.getMetricsHistory(3600000); // Last hour

            console.log('Report Time:', new Date().toISOString());
            console.log('Report Duration: Last 1 hour');
            console.log('');

            // Performance summary
            console.log('📊 Performance Summary:');
            console.log(`   Total Requests: ${summary.summary.totalRequests}`);
            console.log(`   Error Rate: ${summary.summary.errorRate}%`);
            console.log(`   Average Response Time: ${summary.summary.avgResponseTime}ms`);
            console.log(`   Uptime: ${this.formatUptime(summary.summary.uptime)}`);
            console.log('');

            // Request distribution
            const current = summary.current;
            if (current.counters.requests_total > 0) {
                console.log('📈 Request Distribution:');
                const successRate = ((current.counters.requests_success / current.counters.requests_total) * 100).toFixed(1);
                console.log(`   Success: ${successRate}% (${current.counters.requests_success}/${current.counters.requests_total})`);
                console.log(`   Failed: ${(100 - successRate).toFixed(1)}% (${current.counters.requests_failed}/${current.counters.requests_total})`);
                console.log('');
            }

            // Resource usage
            console.log('💻 Resource Usage:');
            const memoryUsage = current.gauges.memory_usage_bytes || 0;
            console.log(`   Memory: ${this.formatBytes(memoryUsage)} (${((memoryUsage / (1024 * 1024 * 1024)) * 100).toFixed(1)}% of 1GB)`);
            console.log(`   CPU: ${current.gauges.cpu_usage_percent || 0}%`);
            console.log(`   Active Connections: ${current.gauges.active_connections || 0}`);
            console.log('');

            // Error breakdown
            if (current.counters.errors_total > 0) {
                console.log('❌ Error Breakdown:');
                console.log(`   Validation Errors: ${current.counters.validation_errors || 0}`);
                console.log(`   Provider Errors: ${current.counters.provider_errors || 0}`);
                console.log(`   Network Errors: ${current.counters.network_errors || 0}`);
                console.log(`   Timeout Errors: ${current.counters.timeout_errors || 0}`);
                console.log('');
            }

            // Provider statistics
            if (current.counters.provider_requests_total > 0) {
                console.log('🔌 Provider Statistics:');
                console.log(`   Total Provider Requests: ${current.counters.provider_requests_total}`);
                console.log(`   Provider Errors: ${current.counters.provider_errors || 0}`);
                const providerErrorRate = ((current.counters.provider_errors / current.counters.provider_requests_total) * 100).toFixed(1);
                console.log(`   Provider Error Rate: ${providerErrorRate}%`);
                console.log('');
            }

            // Image processing statistics
            if (current.counters.image_processing_total > 0) {
                console.log('🖼️  Image Processing Statistics:');
                console.log(`   Total Processing Requests: ${current.counters.image_processing_total}`);
                console.log(`   Successful: ${current.counters.image_processing_success || 0}`);
                console.log(`   Failed: ${current.counters.image_processing_failed || 0}`);
                const processingSuccessRate = ((current.counters.image_processing_success / current.counters.image_processing_total) * 100).toFixed(1);
                console.log(`   Success Rate: ${processingSuccessRate}%`);

                if (current.histograms.image_processing_time_ms && current.histograms.image_processing_time_ms.count > 0) {
                    console.log(`   Avg Processing Time: ${current.histograms.image_processing_time_ms.mean.toFixed(0)}ms`);
                    console.log(`   P95 Processing Time: ${current.histograms.image_processing_time_ms.p95}ms`);
                }
                console.log('');
            }

            // Response time analysis
            if (current.histograms.response_time_ms && current.histograms.response_time_ms.count > 0) {
                console.log('⚡ Response Time Analysis:');
                console.log(`   Count: ${current.histograms.response_time_ms.count}`);
                console.log(`   Mean: ${current.histograms.response_time_ms.mean.toFixed(0)}ms`);
                console.log(`   Median: ${current.histograms.response_time_ms.median}ms`);
                console.log(`   P95: ${current.histograms.response_time_ms.p95}ms`);
                console.log(`   P99: ${current.histograms.response_time_ms.p99}ms`);
                console.log(`   Max: ${current.histograms.response_time_ms.max}ms`);
                console.log('');
            }

            // Timeline data
            if (history.length > 1) {
                console.log('📈 Timeline (Last Hour):');
                console.log('Time                | Requests/s | Errors/s | Memory');
                console.log('--------------------|-----------|----------|--------');

                history.slice(-12).forEach((snapshot, index) => {
                    const time = new Date(snapshot.timestamp).toLocaleTimeString();
                    const requests = snapshot.counters.requests_total || 0;
                    const errors = snapshot.counters.requests_failed || 0;
                    const memory = this.formatBytes(snapshot.gauges.memory_usage_bytes || 0, true);

                    // Calculate rates (simplified)
                    let reqPerSec = 0;
                    let errPerSec = 0;
                    if (index > 0) {
                        const prevSnapshot = history[index - 1];
                        const timeDiff = (snapshot.timestamp - prevSnapshot.timestamp) / 1000;
                        if (timeDiff > 0) {
                            reqPerSec = ((requests - (prevSnapshot.counters.requests_total || 0)) / timeDiff).toFixed(1);
                            errPerSec = ((errors - (prevSnapshot.counters.requests_failed || 0)) / timeDiff).toFixed(1);
                        }
                    }

                    console.log(`${time} | ${reqPerSec.padStart(9)} | ${errPerSec.padStart(8)} | ${memory}`);
                });
            }

        } catch (error) {
            console.error('❌ Failed to generate report:', error.message);
            process.exit(1);
        }
    }

    /**
     * Format uptime
     */
    formatUptime(seconds) {
        const days = Math.floor(seconds / 86400);
        const hours = Math.floor((seconds % 86400) / 3600);
        const minutes = Math.floor((seconds % 3600) / 60);

        if (days > 0) {
            return `${days}d ${hours}h ${minutes}m`;
        } else if (hours > 0) {
            return `${hours}h ${minutes}m`;
        } else {
            return `${minutes}m`;
        }
    }

    /**
     * Format bytes
     */
    formatBytes(bytes, short = false) {
        if (bytes === 0) return '0B';

        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));

        if (short && i > 1) {
            return `${(bytes / Math.pow(k, i)).toFixed(1)}${sizes[i]}`;
        }

        return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
    }

    /**
     * Format duration
     */
    formatDuration(ms) {
        const seconds = Math.floor(ms / 1000);
        const minutes = Math.floor(seconds / 60);
        const hours = Math.floor(minutes / 60);

        if (hours > 0) {
            return `${hours}h ${minutes % 60}m`;
        } else if (minutes > 0) {
            return `${minutes}m ${seconds % 60}s`;
        } else {
            return `${seconds}s`;
        }
    }
}

// CLI interface
async function main() {
    const args = process.argv.slice(2);
    const command = args[0];

    const cli = new MetricsCLI();

    switch (command) {
        case 'current':
        case '':
            await cli.displayCurrentMetrics();
            break;
        case 'history':
            const duration = parseInt(args[1]) || 3600000; // Default 1 hour
            await cli.displayMetricsHistory(duration);
            break;
        case 'health':
            await cli.displayHealthStatus();
            break;
        case 'prometheus':
            await cli.exportPrometheusMetrics();
            break;
        case 'report':
            await cli.generateReport();
            break;
        case 'help':
        case '--help':
        case '-h':
            console.log('Vision Analyzer Metrics CLI');
            console.log('');
            console.log('Usage: npm run metrics [command] [options]');
            console.log('');
            console.log('Commands:');
            console.log('  current    Display current metrics');
            console.log('  history    Display metrics history');
            console.log('  health     Display health status');
            console.log('  prometheus Export metrics in Prometheus format');
            console.log('  report     Generate detailed metrics report');
            console.log('  help       Show this help message');
            console.log('');
            console.log('Options:');
            console.log('  duration   Duration for history (in milliseconds)');
            console.log('');
            console.log('Examples:');
            console.log('  npm run metrics');
            console.log('  npm run metrics history');
            console.log('  npm run metrics history 7200000  # Last 2 hours');
            console.log('  npm run metrics health');
            console.log('  npm run metrics prometheus');
            console.log('  npm run metrics report');
            break;
        default:
            console.error(`Unknown command: ${command}`);
            console.log('Use "npm run metrics help" for usage information');
            process.exit(1);
    }
}

// Run if called directly
if (require.main === module) {
    main().catch(error => {
        console.error('Metrics CLI error:', error);
        process.exit(1);
    });
}

module.exports = MetricsCLI;